package com.swt.testdemo.shiro;


import cn.hutool.core.util.StrUtil;
import com.swt.testdemo.dao.SysMenuDao;
import com.swt.testdemo.dao.SysRoleDao;
import com.swt.testdemo.dao.SysUserDao;
import com.swt.testdemo.entity.SysMenuEntity;
import com.swt.testdemo.entity.SysRoleEntity;
import com.swt.testdemo.entity.SysUserEntity;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 认证
 *
 * @author BleethNie
 * @version 1.0
 * @date 2020-01-09 09:48
 */
@Component
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private SysUserDao sysUserDao;

    @Autowired
    private SysMenuDao sysMenuDao;

    @Autowired
    private SysRoleDao sysRoleDao;


    /**
     * 授权(验证权限时调用)
     *
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SysUserEntity user = (SysUserEntity) principals.getPrimaryPrincipal();
        Integer roleId = user.getRoleId();
        SysRoleEntity sysRoleEntity = sysRoleDao.queryRoleById(roleId);
        String roleType = sysRoleEntity.getRoleType();

        List<String> permsList = new ArrayList<String>();


        //系统管理员，拥有最高权限
        if (SysRoleEntity.ADMIN_TYPE.equals(roleType)) {
            List<SysMenuEntity> menuList = sysMenuDao.selectList(null);
            for (SysMenuEntity menu : menuList) {
                permsList.add(menu.getPerms());
            }
        } else {
            permsList = sysUserDao.queryPermsByRoleId(roleId);
        }

        //用户权限列表
        Set<String> permsSet = new HashSet<>();
        for (String perms : permsList) {
            if (StrUtil.isBlank(perms)) {
                continue;
            }
            permsSet.addAll(Arrays.asList(perms.trim().split(",")));
        }

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(permsSet);
        return info;
    }

    /**
     * 认证(登录时调用)
     *
     * @param authToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authToken) throws AuthenticationException {
        //是否需要mac地址才允许登陆
        boolean swtLoginMac;

        String mac = "";

        String username = "";

        if (authToken instanceof UsernamePasswordMacToken) {
            UsernamePasswordMacToken token = (UsernamePasswordMacToken) authToken;
            mac = token.getMac();
            username = token.getUsername();
            swtLoginMac = true;
        } else {
            UsernamePasswordToken token = (UsernamePasswordToken) authToken;
            username = token.getUsername();
            swtLoginMac = false;
        }

        //查询用户信息
        SysUserEntity user = sysUserDao.selectUserByName(username);
        String userMac = user.getMac();
        if (user == null) {
            throw new UnknownAccountException("账号不存在");
        }
        String userStatus = user.getStatus();
        if (StrUtil.isEmpty(userStatus) || userStatus.equals(SysUserEntity.STATUS_DISABLE)) {
            throw new LockedAccountException("账号已被锁定,请联系管理员");
        }

        if (swtLoginMac) {
            if (StrUtil.isEmpty(mac) || !mac.equals(userMac)) {
                throw new AccountException("账号绑定设备与当前登陆设备不匹配");
            }
        }

        return new SimpleAuthenticationInfo(user, user.getPassword(),
                ByteSource.Util.bytes(user.getSalt()), getName());
    }

    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        HashedCredentialsMatcher shaCredentialsMatcher = new HashedCredentialsMatcher();
        shaCredentialsMatcher.setHashAlgorithmName(ShiroUtils.HASH_ALGORITHM_NAME);
        shaCredentialsMatcher.setHashIterations(ShiroUtils.HASH_ITERATIONS);
        super.setCredentialsMatcher(shaCredentialsMatcher);
    }



}
